/*******************************************************************************
 * Package: com.song.boot.springstudy.thread.lock
 * Type:    ReentrantLockCondition
 * Date:    2024-02-05 15:21
 *
 * Copyright (c) 2024 LTD All Rights Reserved.
 *
 * You may not use this file except in compliance with the License.
 *******************************************************************************/
package com.song.boot.springstudy.thread.lock;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 功能描述：Condition
 * Java中的等待和唤醒需要线程切换。这是为了确保线程安全和资源正确地被访问和修改。
 * @author Songxianyang
 * @date 2024-02-05 15:21
 */
public class ReentrantLockCondition {
    private final Lock lock = new ReentrantLock();
    private final Condition conditionA = lock.newCondition();
    private final Condition conditionB = lock.newCondition();

    private boolean atTurnA = true; // 标识当前是线程A的回合

    public void turnA() {
        lock.lock();
        try {
            // 如果不是线程A的回合，等待
            while (!atTurnA) {
                conditionA.await();
            }
            // 业务逻辑
            System.out.println("Thread A executing");
            // 切换到线程B的回合
            atTurnA = false;
            // 唤醒等待在conditionB上的线程
            conditionB.signal();
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        } finally {
            lock.unlock();
        }
    }

    public void turnB() {
        lock.lock();
        try {
            // 如果不是线程B的回合，等待
            while (atTurnA) {
                conditionB.await();
            }
            // 业务逻辑
            System.out.println("Thread B executing");
            // 切换到线程A的回合
            atTurnA = true;
            // 唤醒等待在conditionA上的线程
            conditionA.signal();
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        } finally {
            lock.unlock();
        }
    }

    public static void main(String[] args) {
        ReentrantLockCondition lockCondition = new ReentrantLockCondition();

        Runnable turnA = () -> {
            lockCondition.turnA();
        };

        Runnable turnB = () -> {
            lockCondition.turnB();
        };

        Thread threadA = new Thread(turnA);
        Thread threadB = new Thread(turnB);

        threadA.start();
        threadB.start();
    }
}
